package com.hitqz.robot.netty;

import com.hitqz.robot.driver.communication.NetworkServiceThreadPool;
import com.hitqz.robot.driver.communication.TcpClient;
import com.hitqz.robot.netty.decoder.Robot2ServerDecoder;
import com.hitqz.robot.netty.encoder.Robot2ServerEncoder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * @author xupkun
 * @date 2023/7/14
 */
@Slf4j
public class NettyClient {

    // 全局唯一的 NettyClient 实例
    private static volatile NettyClient instance;

    // 连接相关的字段
    public static String host = "";
    public static int port = 9876;
    public static String clientId;
    public static TcpClient tcpClient;


    // 私有构造方法，确保外部无法直接创建实例
    private NettyClient() {

    }

    // 获取唯一实例，双重检查锁定确保线程安全
    public static NettyClient getInstance() {
        if (instance == null) {
            synchronized (NettyClient.class) {
                if (instance == null) {
                    instance = new NettyClient();
                }
            }
        }
        return instance;
    }

    // 启动连接并带有重连机制
    public void connect(String clientId, String host, int port) {
        if (Objects.equals(NettyClient.host,host) && Objects.equals(NettyClient.port,port) && tcpClient!=null){
            log.info("tcp client already exist");
            return;
        }
        if (tcpClient!=null){
            try {
                tcpClient.shutdown();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        NettyClient.host = host;
        NettyClient.port = port;
        NettyClient.clientId = clientId;
        tcpClient = new TcpClient("communication", host ,port, new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel channel) throws Exception {
                channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(
                        1024*1024+46, // 最大帧长度（1 MB 数据 ）
                        42,        // 长度字段的偏移量
                        4,         // 长度字段的字节数
                        0,         // 长度调整
                        2         // 初始偏移量 跳过0xEB90
                ));
                channel.pipeline().addLast("decoder", new Robot2ServerDecoder());
                channel.pipeline().addLast("encoder", new Robot2ServerEncoder());
                // 处理类
                channel.pipeline().addLast(new NettyMessageHandler());
            }
        });
        NetworkServiceThreadPool.creatNetworkServerOrClient(()->{
            try {
                tcpClient.connectAsync();
            } catch (Exception e) {
                log.error("[communication] server bind error", e);
            }
        });

    }


    @SneakyThrows
    public void shutdown() {
        if (tcpClient!= null) {
            tcpClient.shutdown();
        }
    }

}